/*
 Copyright (c) [Year] [name of copyright holder]
 [Software Name] is licensed under Mulan PSL v2.
 You can use this software according to the terms and conditions of the Mulan
 PSL v2.
 You may obtain a copy of Mulan PSL v2 at:
          http://license.coscl.org.cn/MulanPSL2
 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 See the Mulan PSL v2 for more details.
*/

#ifndef _1988WJ_PASTEDB_HPP_
#define _1988WJ_PASTEDB_HPP_

#include "PasteIO.hpp"
#include <cstring>
#include <mysql/mysql.h>

class PasteDB {
  private:
    MYSQL *conn = nullptr;

  public:
    /**
     * @brief 数据库操作失败时，抛出一个运行时错误异常
     *
     * 当MariaDB数据库操作失败时，调用此函数抛出一个异常，异常信息包含具体的错误描述
     *
     * @param conn 数据库连接对象
     * @param errStr 错误描述字符串，用于提供更详细的错误信息
     * @param funcName 错误发生时的函数名，用于提供更详细的错误信息
     */
    static void ThrowDBError(MYSQL *conn, const char *funcName, const char *errStr);

    /**
     * @brief 数据库预处理操作失败时，抛出一个运行时错误异常
     *
     * 当MariaDB预处理数据库操作失败时，调用此函数抛出一个异常，异常信息包含具体的错误描述
     *
     * @param stmt 预处理语句对象
     * @param errStr 错误描述字符串，用于提供更详细的错误信息
     * @param funcName 错误发生时的函数名，用于提供更详细的错误信息
     */
    static void ThrowDBError(MYSQL_STMT *stmt, const char *funcName, const char *errStr);

    // 数据库链接字符串
    struct ConnStruct {
        const char *host = nullptr;        // 数据库服务器地址
        const char *user = nullptr;        // 数据库用户名
        const char *passwd = nullptr;      // 数据库用户密码
        const char *db = nullptr;          // 数据库名
        const char *unix_socket = nullptr; // UNIX socket
        unsigned int port = 0;             // 数据库服务器端口
    };

    // 图片信息表结构
    struct ImageStruct {
        char ID0[37] = "";                  // 主键，GUID
        char ID1[37] = "";                  // 图片ID
        int32_t Int0 = 0;                   // 产品数字编号在此表中唯一不重复
        int32_t Int1 = 0;                   // 尺寸1(um)长,直径,内径等最关乎到实际使用的尺寸
        int32_t Int2 = 0;                   // 尺寸2(um)宽
        int32_t Int3 = 0;                   // 尺寸3(um)高
        int32_t Int4 = 0;                   // 质量(mg)净重
        int32_t Int5 = 0;                   // 质量(mg)毛重
        int32_t Int6 = 0;                   // 类别ID
        int32_t Int7 = 0;                   // 材质ID
        char Str0[255] = "";                // 关键字
        char Str1[255] = "";                // 注释说明
        char Time0[32] = "";                // 创建时间
        char Time1[32] = "";                // 更新时间
        char indNone = STMT_INDICATOR_NONE; // 指示器 无语义(0)
        char indNull = STMT_INDICATOR_NULL; // 指示器 空值(1)
        char indNts = STMT_INDICATOR_NTS;   // 指示器 字符串以\0结尾(-1)

        // char indDefault = STMT_INDICATOR_DEFAULT; // 指示器 使用列默认值(2)
        // char indIgnore = STMT_INDICATOR_IGNORE;   // 指示器 跳过列的更新(3)
    };

    // 产品信息表结构
    struct ProductStruct {
        char ID0[37] = "";                  // 主ID
        char ID1[37] = "";                  // 用户ID,暂时存储开发人员
        char ID2[37] = "";                  // 公司ID
        char ID3[37] = "";                  // 图片ID
        int32_t Int0 = 0;                   // 产品数字编号在此表中唯一不重复(主表暂时当主键)
        int32_t Int1 = 0;                   // 尺寸1(um)长,直径,内径等最关乎到实际使用的尺寸
        int32_t Int2 = 0;                   // 尺寸2(um)宽
        int32_t Int3 = 0;                   // 尺寸2(um)高
        int32_t Int4 = 0;                   // 质量(mg)净重
        int32_t Int5 = 0;                   // 质量(mg)毛重
        int32_t Int6 = 0;                   // 类别ID
        int32_t Int7 = 0;                   // 材质ID(辅表暂时当主键)
        int64_t Big0 = 0;                   // 单价(1毫元)小数点后4位
        int64_t Big1 = 0;                   // 金额(1毫元)小数点后4位
        char Str0[255] = "";                // 名称
        char Str1[255] = "";                // 字符串编号款号可重复可有文字付号
        char Str2[255] = "";                // 规格型号
        char Str3[255] = "";                // 计量单位
        char Str4[255] = "";                // 重复数据差异暂存区域
        char Str5[255] = "";                // 关键字
        char Str6[255] = "";                // 产品备注
        char Str7[255] = "";                // 注释说明
        char Time0[32] = "";                // 创建时间
        char Time1[32] = "";                // 更新时间
        char indNone = STMT_INDICATOR_NONE; // 指示器 无语义(0)
        char indNull = STMT_INDICATOR_NULL; // 指示器 空值(1)
        char indNts = STMT_INDICATOR_NTS;   // 指示器 字符串以\0结尾(-1)

        // char indDefault = STMT_INDICATOR_DEFAULT; // 指示器 使用列默认值(2)
        // char indIgnore = STMT_INDICATOR_IGNORE;   // 指示器 跳过列的更新(3)
    };

    /**
     * @brief 构造函数：负责初始化数据库连接并选择指定的数据库
     *
     * 此构造函数用于初始化数据库连接的参数，包括服务器地址、用户名、密码、数据库名和端口
     * 它为类的成员变量赋值，以便后续进行数据库连接和操作
     * @param host 数据库服务器地址
     * @param user 数据库用户名
     * @param passwd 数据库用户密码
     * @param db 要连接的数据库名
     * @param port 数据库服务器端口
     */
    PasteDB(const ConnStruct &connStr);
    ~PasteDB();

    /**
     * @brief 在`ImageInfo`主表或`ImageInfo2`辅表中插入图像信息列表。
     *
     * 该函数通过接收一个图像信息结构体数组，向数据库中插入多个图像记录。
     *
     * @param imgInfoArr 图像信息数组，包含多个ImageStruct结构体。
     * @param isMainTable true表示插入到主表，false表示插入到辅表
     */
    void ImageListInsert(std::vector<ImageStruct> &imgInfoArr, bool isMainTable = true);

    /**
     * @brief 从`ImageInfo`主表或`ImageInfo2`辅表中查询特定类别的图像列表
     *
     * 此函数根据给定的类别ID从图像数据库中选择图像列表，并将结果存储在imgInfoOut参数中
     *
     * @param imgInfoArrOut 输出参数，包含选定图像信息的向量
     * @param categoryID 图像的类别ID，用于限制查询的范围
     * @param isMainTable true表示从主表查询，false表示从辅表查询
     */
    void ImageListSelect(std::vector<ImageStruct> &imgInfoArrOut, int categoryID, bool isMainTable = true);

    /**
     * @brief 更新`ImageInfo`主表或`ImageInfo2`辅表中关键字信息
     *
     * @param imgInfoArr 图像信息数组，这是一个包含多个ImageStruct结构的向量，每个结构都描述了一个图像的信息
     * @param isMainTable true表示更新主表，false表示更新辅表
     */
    void ImageListUpdateKey(std::vector<ImageStruct> &imgInfoArr, bool isMainTable = true);

    /**
     * @brief 从`ProductInfo`主表或`ProductInfo2`辅表中删除指定的产品信息。
     *
     * @param productNum 要删除的产品编号。
     * @param isMainTable true表示插入到主表，false表示插入到辅表
     */
    void ProductDelete(int productNum, bool isMainTable = true);

    /**
     * @brief 在`ProductInfo`主表或`ProductInfo2`辅表中插入产品信息
     *
     * 此函数用于向数据库中插入一个产品的信息，根据isMainTable参数决定是插入到主表还是辅表
     *
     * @param productInfo 产品信息
     * @param isMainTable true表示插入到主表，false表示插入到辅表
     */
    void ProductInsert(ProductStruct &productInfo, bool isMainTable = true);

    /**
     * @brief 在`ProductInfo`主表或`ProductInfo2`辅表中批量插入产品信息
     *
     * 此函数负责将一批产品信息插入到数据库中，根据isMainTable参数决定是插入到主表还是辅表
     *
     * @param productInfoArr 产品信息数组，通过引用传递这允许函数直接修改原始数据
     * @param isMainTable true表示插入到主表，false表示插入到辅表
     */
    void ProductListInsert(std::vector<ProductStruct> &productInfoArr, bool isMainTable = true);

    /**
     * @brief 从`ProductInfo`主表或`ProductInfo2`辅表中查询产品信息
     *
     * 此函数根据提供的参数从数据库中查询相应的产品信息，并通过引用参数productInfoOut返回
     * 它允许用户根据需要从主表或辅表中查询产品，并可以根据特定类别进行筛选
     *
     * @param productInfoOut 用于存储从数据库中获取的产品信息的结构体引用
     * @param productNum 需要查询的产品编号
     * @param categoryID 产品的类别ID，用于限制查询的范围
     * @param isMainTable true表示从主表查询，false表示从辅表查询
     */
    void ProductSelect(ProductStruct &productInfoOut, int productNum, int categoryID = -1, bool isMainTable = true);

    /**
     * @brief 往`ProductInfo`主表或`ProductInfo2`辅表中图片ID字段中插入图片ID
     *
     * 该函数用于更新指定产品的图片ID
     *
     * @param productNum 产品编号，用于标识需要更新图片ID的产品
     * @param imageID 指向图片ID的字符数组(去吃'-'的UUID)，表示要更新的图片ID
     * @param isMainTable true表示更新主表，false表示更新辅表
     */
    void ProductUpdate(ProductStruct &productInfo, bool isMainTable = true);

    /**
     * @brief 从`ProductInfo2`辅表中查询产品信息列表
     *
     * 辅表中产品编号会有重复，所以需要根据产品编号查询信息列表
     *
     * @param productInfoArrOut 用于存储从数据库中获取的产品信息列表的结构体引用
     * @param productNum 需要查询的产品编号
     */
    void Product2ListSelect(std::vector<ProductStruct> &productInfoArrOut, int productNum);
};
#endif